/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    usart_if.c
  * @author  MCD Application Team
  * @brief   Configuration of UART driver interface for hyperterminal communication
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "usart_if.h"

/* USER CODE BEGIN Includes */
#include "alarm_network.h"
#include "node_config.h"
#include <ctype.h>
/* USER CODE END Includes */

/* External variables ---------------------------------------------------------*/
/**
  * @brief DMA handle
  */
extern DMA_HandleTypeDef hdma_usart2_tx;

/**
  * @brief UART handle
  */
extern UART_HandleTypeDef huart2;

/**
  * @brief buffer to receive 1 character
  */
uint8_t charRx;

/* USER CODE BEGIN EV */

/* USER CODE END EV */

/* Private typedef -----------------------------------------------------------*/
/**
  * @brief Trace driver callbacks handler
  */
const UTIL_ADV_TRACE_Driver_s UTIL_TraceDriver =
{
  vcom_Init,
  vcom_DeInit,
  vcom_ReceiveInit,
  vcom_Trace_DMA,
};

/* USER CODE BEGIN PTD */
unsigned char RxBufU1;
unsigned char RxBufU2;
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define UTF8_ENABLE 1  // 启用UTF-8支持

// UTF-8字符长度定义
#define UTF8_1BYTE_MASK     0x80  // 0xxxxxxx
#define UTF8_2BYTE_MASK     0xE0  // 110xxxxx
#define UTF8_3BYTE_MASK     0xF0  // 1110xxxx
#define UTF8_4BYTE_MASK     0xF8  // 11110xxx
#define UTF8_2BYTE_PREFIX   0xC0  // 110xxxxx
#define UTF8_3BYTE_PREFIX   0xE0  // 1110xxxx
#define UTF8_4BYTE_PREFIX   0xF0  // 11110xxx
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/**
  * @brief  TX complete callback
  * @return none
  */
static void (*TxCpltCallback)(void *);
/**
  * @brief  RX complete callback
  * @param  rxChar ptr of chars buffer sent by user
  * @param  size buffer size
  * @param  error errorcode
  * @return none
  */
static void (*RxCpltCallback)(uint8_t *rxChar, uint16_t size, uint8_t error);

/* USER CODE BEGIN PV */
/* 传感器超限检测标志 */
volatile uint8_t sensor1_alarm = 0;
volatile uint8_t sensor2_alarm = 0;

/* 传感器ID定义 */
#define SENSOR_UART1_ID 1
#define SENSOR_UART2_ID 2

/* 雷达传感器最后报警时间记录 */
volatile uint32_t radar1_last_alarm_time = 0;
volatile uint32_t radar2_last_alarm_time = 0;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
static int get_utf8_char_length(uint8_t first_byte);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Exported functions --------------------------------------------------------*/

UTIL_ADV_TRACE_Status_t vcom_Init(void (*cb)(void *))
{
  /* USER CODE BEGIN vcom_Init_1 */

  /* USER CODE END vcom_Init_1 */
  TxCpltCallback = cb;
  MX_DMA_Init();
  MX_USART2_UART_Init();
  LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_27);
  return UTIL_ADV_TRACE_OK;
  /* USER CODE BEGIN vcom_Init_2 */

  /* USER CODE END vcom_Init_2 */
}

UTIL_ADV_TRACE_Status_t vcom_DeInit(void)
{
  /* USER CODE BEGIN vcom_DeInit_1 */

  /* USER CODE END vcom_DeInit_1 */
  /* ##-1- Reset peripherals ################################################## */
  __HAL_RCC_USART2_FORCE_RESET();
  __HAL_RCC_USART2_RELEASE_RESET();

  /* ##-2- MspDeInit ################################################## */
  HAL_UART_MspDeInit(&huart2);

  /* ##-3- Disable the NVIC for DMA ########################################### */
  /* USER CODE BEGIN 1 */
  HAL_NVIC_DisableIRQ(DMA1_Channel5_IRQn);

  return UTIL_ADV_TRACE_OK;
  /* USER CODE END 1 */
  /* USER CODE BEGIN vcom_DeInit_2 */

  /* USER CODE END vcom_DeInit_2 */
}

/**
  * @brief  获取UTF-8字符的字节长度
  * @param  first_byte: UTF-8字符的第一个字节
  * @retval 字符的字节长度
  */
static int get_utf8_char_length(uint8_t first_byte)
{
  if ((first_byte & UTF8_1BYTE_MASK) == 0x00) {
    return 1; // ASCII字符
  } else if ((first_byte & UTF8_2BYTE_MASK) == UTF8_2BYTE_PREFIX) {
    return 2; // 2字节UTF-8字符
  } else if ((first_byte & UTF8_3BYTE_MASK) == UTF8_3BYTE_PREFIX) {
    return 3; // 3字节UTF-8字符
  } else if ((first_byte & UTF8_4BYTE_MASK) == UTF8_4BYTE_PREFIX) {
    return 4; // 4字节UTF-8字符
  }
  return 1; // 未知格式，当作单字节处理
}

#if UTF8_ENABLE
/**
  * @brief  UTF-8字符传输函数
  * @param  p_data: 要发送的数据指针
  * @param  size: 数据大小
  * @retval None
  */
void vcom_Trace_UTF8(uint8_t *p_data, uint16_t size)
{
  /* USER CODE BEGIN vcom_Trace_UTF8_1 */
  uint16_t i = 0;
  
  // 确保UART传输完成后再发送下一个字符
  // 这样可以避免UTF-8多字节字符被中断分割
  while (i < size)
  {
    // 获取当前UTF-8字符的长度
    int char_len = get_utf8_char_length(p_data[i]);
    
    // 确保不会超出缓冲区
    if (i + char_len <= size)
    {
      // 发送整个UTF-8字符序列
      HAL_UART_Transmit(&huart2, &p_data[i], char_len, 1000);
      i += char_len;
    }
    else
    {
      // 如果剩余数据不足一个完整字符，按单字节发送
      HAL_UART_Transmit(&huart2, &p_data[i], 1, 1000);
      i++;
    }
  }
  /* USER CODE END vcom_Trace_UTF8_1 */
}
#endif

void vcom_Trace(uint8_t *p_data, uint16_t size)
{
  /* USER CODE BEGIN vcom_Trace_1 */
#if UTF8_ENABLE
  vcom_Trace_UTF8(p_data, size);
#else
  HAL_UART_Transmit(&huart2, p_data, size, 1000);
#endif
  /* USER CODE END vcom_Trace_1 */
}

UTIL_ADV_TRACE_Status_t vcom_Trace_DMA(uint8_t *p_data, uint16_t size)
{
  /* USER CODE BEGIN vcom_Trace_DMA_1 */
#if UTF8_ENABLE
  // 对于DMA传输，我们仍然使用原始函数，但在接收端需要正确处理UTF-8
  HAL_UART_Transmit_DMA(&huart2, p_data, size);
#else
  HAL_UART_Transmit_DMA(&huart2, p_data, size);
#endif
  return UTIL_ADV_TRACE_OK;
  /* USER CODE BEGIN vcom_Trace_DMA_2 */

  /* USER CODE END vcom_Trace_DMA_2 */
}

UTIL_ADV_TRACE_Status_t vcom_ReceiveInit(void (*RxCb)(uint8_t *rxChar, uint16_t size, uint8_t error))
{
  /* USER CODE BEGIN vcom_ReceiveInit_1 */

  /* USER CODE END vcom_ReceiveInit_1 */
  UART_WakeUpTypeDef WakeUpSelection;

  /*record call back*/
  RxCpltCallback = RxCb;

  /*Set wakeUp event on start bit*/
  WakeUpSelection.WakeUpEvent = UART_WAKEUP_ON_STARTBIT;

  HAL_UARTEx_StopModeWakeUpSourceConfig(&huart2, WakeUpSelection);

  /* Make sure that no UART transfer is on-going */
  while (__HAL_UART_GET_FLAG(&huart2, USART_ISR_BUSY) == SET);

  /* Make sure that UART is ready to receive)   */
  while (__HAL_UART_GET_FLAG(&huart2, USART_ISR_REACK) == RESET);

  /* Enable USART interrupt */
  __HAL_UART_ENABLE_IT(&huart2, UART_IT_WUF);

  /*Enable wakeup from stop mode*/
  HAL_UARTEx_EnableStopMode(&huart2);

  /*Start LPUART receive on IT*/
  HAL_UART_Receive_IT(&huart2, &charRx, 1);

  return UTIL_ADV_TRACE_OK;
  /* USER CODE BEGIN vcom_ReceiveInit_2 */

  /* USER CODE END vcom_ReceiveInit_2 */
}

void vcom_Resume(void)
{
  /* USER CODE BEGIN vcom_Resume_1 */

  /* USER CODE END vcom_Resume_1 */
  /*to re-enable lost UART settings*/
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }

  /*to re-enable lost DMA settings*/
  if (HAL_DMA_Init(&hdma_usart2_tx) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN vcom_Resume_2 */

  /* USER CODE END vcom_Resume_2 */
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
  /* USER CODE BEGIN HAL_UART_TxCpltCallback_1 */

  /* USER CODE END HAL_UART_TxCpltCallback_1 */
  /* buffer transmission complete*/
  if (huart->Instance == USART2)
  {
    TxCpltCallback(NULL);
  }
  /* USER CODE BEGIN HAL_UART_TxCpltCallback_2 */

  /* USER CODE END HAL_UART_TxCpltCallback_2 */
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* USER CODE BEGIN HAL_UART_RxCpltCallback_1 */

  /* USER CODE END HAL_UART_RxCpltCallback_1 */

  /* USER CODE BEGIN HAL_UART_RxCpltCallback_2 */
  /* 传感器数据处理 - 采集端专用 */
#ifdef NODE_TYPE_COLLECTOR
  if (huart->Instance == USART1)
  {
    
    /* 检查是否为ASCII数字字符 (0-9) */
    if (RxBufU1 >= '0' && RxBufU1 <= '9')
    {
      ProcessSensorData(SENSOR_UART1_ID, 1);   
    }
    HAL_UART_Receive_IT(&huart1, &RxBufU1, 1);

  }
  else if (huart->Instance == USART2)
  {
    /* 检查是否为ASCII数字字符 (0-9) */
    if (RxBufU2 >= '0' && RxBufU2 <= '9')
    {
      
      ProcessSensorData(SENSOR_UART2_ID, 1);

    }
    
    HAL_UART_Receive_IT(&huart2, &RxBufU2, 1);

  } 
#endif
  /* USER CODE END HAL_UART_RxCpltCallback_2 */
}

/* USER CODE BEGIN EF */

/**
 * @brief 获取传感器报警状态
 * @param sensor_id 传感器ID (1:UART1, 2:UART2)
 * @return 1:报警状态, 0:正常状态
 */
uint8_t GetSensorAlarmStatus(uint8_t sensor_id)
{
    if (sensor_id == SENSOR_UART1_ID)
    {
        return sensor1_alarm;
    }
    else if (sensor_id == SENSOR_UART2_ID)
    {
        return sensor2_alarm;
    }
    return 0;
}

/**
 * @brief 清除传感器报警状态
 * @param sensor_id 传感器ID (1:UART1, 2:UART2)
 */
void ClearSensorAlarm(uint8_t sensor_id)
{
    if (sensor_id == SENSOR_UART1_ID)
    {
        sensor1_alarm = 0;
    }
    else if (sensor_id == SENSOR_UART2_ID)
    {
        sensor2_alarm = 0;
    }
}

void umodConfigSet(void)
{
  // 启用UART1和UART2接收中断
  HAL_UART_Receive_IT(&huart1, &RxBufU1, 1);
  HAL_UART_Receive_IT(&huart2, &RxBufU2, 1);
  
  // 初始化传感器状态
  sensor1_alarm = 0;
  sensor2_alarm = 0;
  

}
/* USER CODE END EF */

/* Private Functions Definition -----------------------------------------------*/

/* USER CODE BEGIN PrFD */

/* USER CODE END PrFD */